#include <memory.h>
#include <stdbool.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <stdbool.h>
#include "pal/lane_cmd_parse.h"
#include "pal/lane_control.h"
#include "CxlUtil.h"
#include "userLog.h"
#include <sys/wait.h>
#include "common/pidfile.h"
#include "voiceChedaoji.h"

static void handleOneFrame(uint8_t *buf, ssize_t len);
static void parseCmd(uv_work_t *workReq);
static void laneAfterQueueWorkCb(uv_work_t *workReq, int32_t status);
static uint8_t reserveFrame[1024 * 2];

void cmd_parse_queue_work(const uv_buf_t *buf, ssize_t len)
{
    uv_buf_t *tmpBuf = (uv_buf_t *)malloc(sizeof(uv_buf_t));
    ReserveFrameT *reserveFrame = getReserveFrame();
    if (reserveFrame->isReserve == true)
    {
        // 处理粘包情况
        reserveFrame->isReserve = false;
        tmpBuf->base = (uint8_t *)malloc(reserveFrame->reserveLen + len);
        tmpBuf->len = reserveFrame->reserveLen + len;
        memcpy(tmpBuf->base, reserveFrame->reserveBuf, reserveFrame->reserveLen);
        memcpy(tmpBuf->base + reserveFrame->reserveLen, buf->base, len);
    }
    else
    {
        tmpBuf->base = (uint8_t *)malloc(len);
        tmpBuf->len = len;
        memcpy(tmpBuf->base, buf->base, len);
        // hzlog_info(userLog, tmpBuf->base, len);
    }

    head_t *nowHead = (head_t *)tmpBuf->base;
    uint16_t firstFrameLen = getFrameLen(nowHead);
    ssize_t recvLen = tmpBuf->len;

    if (firstFrameLen != tmpBuf->len)
    {
        uint16_t frameNum = howManyFrame(tmpBuf, tmpBuf->len);
        size_t i = 0;
        for (i = 0; i < frameNum; i++)
        {
            uint16_t frameLen = getFrameLen(nowHead);
            handleOneFrame((uint8_t *)nowHead, frameLen);
            recvLen -= frameLen;
            if (recvLen > 0)
            {
                nowHead = headForwardPoint(nowHead, frameLen);
            }
        }
    }
    else
    {
        handleOneFrame((uint8_t *)nowHead, tmpBuf->len);
    }
    free(tmpBuf->base);
    free(tmpBuf);
}

static void handleOneFrame(uint8_t *buf, ssize_t len)
{
    if (checkLen((head_t *)buf, len) == false)
    {
        return;
    }

    uv_loop_t *loop = getLoop();
    uv_buf_t *copyBuf = (uv_buf_t *)malloc(sizeof(uv_buf_t));
    uv_work_t *workReq = (uv_work_t *)malloc(sizeof(uv_work_t));
    uint8_t *dataBuf = (uint8_t *)malloc(len);

    memcpy(dataBuf, buf, len);

    copyBuf->base = dataBuf;
    copyBuf->len = len;
    workReq->data = copyBuf;

    head_t *head = (head_t *)buf;

    uv_queue_work(loop, workReq, parseCmd, laneAfterQueueWorkCb);
}

static void parseCmd(uv_work_t *workReq)
{
    uv_buf_t *buf = (uv_buf_t *)workReq->data;
    head_t *head = (head_t *)buf->base;
    uint16_t head_len = ntohs(head->len);

    switch (head->cmd)
    {
    /* 注册响应 */
    case REGISTER_CMD:
    {
        respon_registration_t *reg_result = (respon_registration_t *)buf->base;
        if (checkCrc(head, buf->len) == false)
        {
            return;
        }
        handleRegisterCmd(reg_result);
        break;
    }

    /* 心跳响应 */
    case HEART_BEAT_CMD:
    {
        respon_heart_beat_t *heart_beat_result = (respon_heart_beat_t *)buf->base;
        // 心跳响应包打印
        // hzlog_info(userLog, heart_beat_result, buf->len);
        if (checkCrc(head, buf->len) == false)
        {
            return;
        }
        handleHeartBeatCmd(heart_beat_result);
        break;
    }

    /* 固件下发 */
    case FIRMWARE_CMD:
    {
        file_block_frame_t *pack = (file_block_frame_t *)buf->base;

        if (checkCrc(head, buf->len) == false)
        {
            return;
        }
        handleFileBlockFrameCmd(pack, buf->len);
        break;
    }

    /* 图片上传回应 */
    case PIC_UPLOAD_CMD:
    {
        respon_pic_block_recv_t *pack = (respon_pic_block_recv_t *)buf->base;

        if (checkCrc(head, buf->len) == false)
        {
            return;
        }
        handlePicUploadRecvCmd(pack);
        break;
    }

    /* 上传标定 */
    case CALIBRATION_CMD:
    {
        respon_calibration_t *calibration = (respon_calibration_t *)buf->base;
        if (checkCrc(head, buf->len) == false)
        {
            return;
        }
        audioRecvCalibration();

        handleCalibrationRecvCmd(calibration);
        break;
    }

    /* 上传标定v2 */
    case CALIBRATION_CMD_V2:
    {
        respon_calibration_v2_t *calibration = (respon_calibration_v2_t *)buf->base;
        if (checkCrc(head, buf->len) == false)
        {
            return;
        }
        handleCalibrationRecvCmdV2(calibration);
        break;
    }
    default:
        break;
    }
}

static void laneAfterQueueWorkCb(uv_work_t *workReq, int32_t status)
{
    uv_buf_t *buf = (uv_buf_t *)workReq->data;
    free(buf->base);
    free(workReq->data);
    free(workReq);
}